package com.object.oriented.exam.system3.entity.po;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.object.oriented.exam.system1.entity.Knowledge;
import com.object.oriented.exam.system1.entity.Problem;
import com.object.oriented.exam.system3.entity.dto.SurveyRuleParam;
import lombok.Data;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Data
@TableName("t_paper")
public class Paper implements Serializable {

    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 总分 1
     */
    private Integer totalScore;

    /**
     * 试卷适应度 2
     */
    private Double adaptationDegree;

    /**
     * 试卷总体难度 （难度*分数/总分） 2
     */
    private Double totalDifficulty;

    /**
     * 知识覆盖度 2
     */
    private Double knowledgeCoverage;

    /**
     * 试卷题目 2
     */
    @TableField(exist = false)
    private List<Problem> problems;

    /**
     * 试卷题目分值 2
     */
    @TableField(exist = false)
    private List<PaperProblem> paperProblems;

    /**
     * 是否是自动组卷 false
     */
    private Boolean isAuto;


    /**
     * 判断是否有相同的题目
     * @param problem
     * @return
     */
    public boolean containProblem(Problem problem) {
        if(problems == null){
            return false;
        }
        for (Problem tempP : problems) {
            if(tempP.getId().equals(problem.getId())){
                return true;
            }
        }
        return false;
    }

    /**
     * 添加问题
     * @param problem
     */
    public void addProblem(Problem problem) {
        if(problems == null){
            problems = new ArrayList<>();
        }
        problems.add(problem);
    }

    //计算总体适应度
    public void calculateAdaptationDegree(SurveyRuleParam surveyRuleParam,int knowNum,Double ratioDifficulty,Double ratioKnowledge) {
        calculateDifficulty();
        calculateKnowledgeCoverage(knowNum);
        this.adaptationDegree = 1 - (1 - getKnowledgeCoverage()) * ratioKnowledge - Math.abs(surveyRuleParam.getDifficulty() - getTotalDifficulty()) / 10 * ratioDifficulty;
    }

    //计算知识点覆盖率
    public void calculateKnowledgeCoverage(int denominator){
        if(problems == null || denominator <= 0){
            return ;
        }
        int numerator = problems.stream().map(Problem::getKnowledgeId).collect(Collectors.toSet()).size();
        this.knowledgeCoverage = numerator * 1.0 / denominator;
    }

    //计算总体难度 用默认分来算就不会被各种规则限制
    public void calculateDifficulty(){
        if(problems == null){
            return ;
        }
        //计算默认总分
        int tScore = problems.stream().map(Problem::getDefaultScore).reduce(0, Integer::sum);
        //计算难度系数
        this.totalDifficulty = Double.valueOf(problems.stream().map(p -> {
            return p.getDifficulty() * p.getDefaultScore() / tScore;
        }).reduce(0, Integer::sum));
    }

    public boolean containsQuestion(Problem problem) {
        if(problems == null){
            return false;
        }
        for (Problem problem1 : problems) {
            if(problem1.getId().equals(problem.getId())){
                return true;
            }
        }
        return false;
    }
}
